package com.intpro.demo.Utils;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.intpro.demo.DAO.User;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Security;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.tomcat.util.codec.binary.Base64;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

public class AESToken
{

	private static final String SECRET_KEY_1 = "751f621ea5c8f930";
	private static final String SECRET_KEY_2 = "2624750004598718";
	private static final String KEY = "wdnmdrg";


	private static IvParameterSpec ivParameterSpec;
	private static SecretKeySpec secretKeySpec;
	private static Cipher cipher;

	static
	{
		Security.addProvider(new BouncyCastleProvider());
		ivParameterSpec = new IvParameterSpec(SECRET_KEY_2.getBytes());
		secretKeySpec = new SecretKeySpec(SECRET_KEY_1.getBytes(), "AES");
		try
		{
			cipher = Cipher.getInstance("AES/CBC/PKCS7PADDING", "BC");
		} catch (Exception e)
		{
			e.printStackTrace();
		}
	}

	public AESToken()
	{
	}


	public static String encrypt(String toBeEncrypt)
			throws InvalidAlgorithmParameterException, InvalidKeyException,
			BadPaddingException, IllegalBlockSizeException
	{
		cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
		byte[] encrypted = cipher.doFinal(toBeEncrypt.getBytes());
		return Base64.encodeBase64String(encrypted);
	}


	public static String decrypt(String encrypted)
			throws InvalidAlgorithmParameterException, InvalidKeyException,
			BadPaddingException, IllegalBlockSizeException
	{
		cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
		byte[] decryptedBytes = cipher.doFinal(Base64.decodeBase64(encrypted));
		return new String(decryptedBytes);
	}


	public static String getToken(User user) throws Exception
	{
		Map<String, String> bearer = new HashMap<>();
		bearer.put("KEY", KEY);
		bearer.put("User", user.account);
		bearer.put("UserId", String.valueOf(user.id));
		bearer.put("CreateTime", DateUtil.timeFormat(new Date()));

		return encrypt(JsonUtil.objectToJson(bearer));
	}

	public static long verifyToken(String token) throws Exception
	{
		Map<String, String> bearer = JsonUtil
				.jsonToObject(decrypt(token), new TypeReference<Map<String, String>>()
				{
				});
		if (bearer == null)
		{
			throw new Exception();
		}
		if (!bearer.get("KEY").equals(KEY))
		{
			throw new Exception();
		}

		return Long.parseLong(bearer.get("UserId"));
	}

}

